import axios from 'axios'
import type {
  AxiosInstance,
  AxiosError,
  AxiosRequestConfig,
  AxiosResponse
} from 'axios'
import NProgress from 'nprogress'
import { ElMessage } from 'element-plus'
import { defaultSetting } from '@/config/setting'
import { getToken } from '@/utils'

/* 服务器返回数据的的类型，根据接口文档确定 */
export interface Result<T = any> {
  code: number
  message: string
  data: T
}

const service: AxiosInstance = axios.create({
  baseURL: defaultSetting.BASE_URL,
  timeout: defaultSetting.TIME_OUT
})

/* 请求拦截器 */
service.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    NProgress.start()
    const token = getToken()
    if (config.headers && token) {
      config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
  },
  (error: AxiosError) => {
    NProgress.done()
    return Promise.reject(error)
  }
)

/* 响应拦截器 */
service.interceptors.response.use(
  (response: AxiosResponse) => {
    NProgress.done()
    let { code, message, data } = response.data

    if (code != 0) {
      ElMessage.warning(message)
    }

    // 处理业务错误
    // const status = data.status
    // switch (status) {
    //   case 401:
    //     message = 'token 失效，请重新登录'
    //     // 这里可以触发退出的 action
    //     break
    //   case 403:
    //     message = '拒绝访问'
    //     break
    //   case 404:
    //     message = '请求地址错误'
    //     break
    //   case 500:
    //     message = '服务器故障'
    //     break
    //   default:
    //   // message = '网络连接故障';
    // }

    return data
  },
  (error: AxiosError) => {
    NProgress.done()
    return Promise.reject(error)
  }
)

/* 导出封装的请求方法 */
const http = {
  get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return service.get(url, config)
  },

  post<T = any>(
    url: string,
    data?: object,
    config?: AxiosRequestConfig
  ): Promise<T> {
    return service.post(url, data, config)
  },

  put<T = any>(
    url: string,
    data?: object,
    config?: AxiosRequestConfig
  ): Promise<T> {
    return service.put(url, data, config)
  },

  delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return service.delete(url, config)
  }
}

export default http
